#include "app_lora.h"
#include "stdio.h"
#include "string.h"
#include "usart.h"
#include "crc.h"


#include "led_test.h"

rt_sem_t    sem_LoraRx;     //读环形缓冲区信号量
rt_mq_t		mq_Lora_rx;		//Lora消息接收队列
rt_mq_t		mq_Lora_tx;		//Lora消息接收队列

#define DeBug 0

//定义环形缓冲区
lora_buffer_t lora_rx_buff;


//写环形缓冲区
uint8_t sbuffer_write(uint8_t w, lora_buffer_t* buf)
{
	//注意：写入的的地址，不能大于读的位置。
	
	//获取写入的地址
    int32_t i = (buf->wr + 1) % BUFFER_MAX;
    
    if(i != buf->rd)	//如果写入的地址不等于读的地址
    {		
        buf->buffer[buf->wr] = w;	//将数据写入
        buf->wr = i;				//更新写入位置
        return 1;					//返回成功
    }
    return 0;
    
}

//读环形缓冲区
uint8_t sbuffer_read(uint8_t* r, lora_buffer_t* buf)
{
	//读的位置 = 写的位置，意为没有东西可读
    if(buf->rd == buf->wr)
        return 0;
    else
    {	
		//否则读出数据，更新rd
        *r = buf->buffer[buf->rd];
        buf->rd = (buf->rd + 1) % BUFFER_MAX;
        return 1;
    }
    
}

//写一个字节的环形缓冲区
uint8_t lora_buf_write_byte(uint8_t w)
{
    /* 写环形缓冲区 */
    if(sbuffer_write(w, &lora_rx_buff))	//写入成功则释放信号量
    {
        /* 释放信号量 */
        rt_sem_release(sem_LoraRx);
        return 1;
    }
    return 0;
}

//读一个字节的环形缓冲区
uint8_t lora_buf_read_byte(uint8_t* r, rt_int32_t time)
{
    /* 等待一个信号量 */
    rt_sem_take(sem_LoraRx, time);
    
    /* 返回读的结果 */
    return sbuffer_read(r, &lora_rx_buff);
}

//读环形缓冲区任务
void app_lora_rx_thread(void* parameter)
{
    uint8_t data;
    uint8_t data_pre = 0;
    uint8_t isRec = RT_FALSE;
    uint8_t *recv = RT_NULL;
    uint8_t i = 0;

    while(1)
    {
        /* 读一个字节，读不到一直等 */
        if(lora_buf_read_byte(&data, RT_WAITING_FOREVER))
        {
            if(data == LR_FRAME_HEAD_L && data_pre == LR_FRAME_HEAD_H && !isRec)
            {
                //判断为帧头
                isRec = RT_TRUE;
                i = 0;
                recv = rt_malloc(MAX_FRAME_LEN); //单位为字节
                if (recv == RT_NULL) {
                    // 内存分配失败，处理错误
                    isRec = RT_FALSE;
					printf("error: app_lora_rx_thread err01");
                    continue;
                }
            }
            else if(data == LR_FRAME_END_L && data_pre == LR_FRAME_END_H && isRec)
            {
                //判断为帧尾
                if (i > 0) {
                    recv[i-1] = '\0'; //将帧尾H替换为\0
                }
                
                if (recv != RT_NULL) {
                    // 将接收到的消息发送到队列中
                    rt_mq_send(mq_Lora_rx, recv, i); // 发送接收到的数据,发送的数据地址为recv， 长度为 i字节
                    rt_free(recv); // 释放内存
                }
				
				isRec = RT_FALSE;
                recv = RT_NULL;
                i = 0;
            }
            else if(isRec && i < MAX_FRAME_LEN - 1)
            {
                recv[i++] = data; // 判断到帧头后开始填充数据
            }
            else	
            {
				//其他情况直接释放内存
                if (recv != RT_NULL) {
                    rt_free(recv);
                }
                recv = RT_NULL;
                isRec = RT_FALSE;
                i = 0;
            }

            /* 记录上一个data */
            data_pre = data;
        }
    }
}

// 解析测试LED模块的查询命令
void parse_test_led_query(uint8_t *buf) {
    switch (buf[0]) { // 定位寄存器
        case LR_FRAME_TEST_LED_STATE:
            
            break;
        default:
            rt_kprintf("Invalid register for test LED query!\n");
            break;
    }
}

// 解析测试LED模块的设置命令
void parse_test_led_set(uint8_t *buf) {
    if (buf[2] == 0x01) { 		// 定位寄存器
        if (buf[3] == 0x01)	//定位数据长度
		{
			if(buf[4] == 0x01)		//确定数据值
			{
				led_on();
				rt_mq_send(mq_Lora_tx, &buf[1], 1+1+1+buf[3]); // 发送模块码+寄存器+数据长度+数据到发送消息队列
			}
			else if (buf[4] == 0x00)
			{
				led_off();
				rt_mq_send(mq_Lora_tx, &buf[1], 1+1+1+buf[3]); // 发送模块码+寄存器+数据长度+数据到发送消息队列
			}
			else
				rt_kprintf("parse_test_led_set: Invalid value for test LED state set!\n");
		}
        else
            rt_kprintf("parse_test_led_set: Invalid value for test LED state set!\n");
    } else {
        rt_kprintf("parse_test_led_set: The register for testing the LED Settings is invalid!\n");
    }
}
// 主机查询命令解析
void lora_cmd_query_parse(uint8_t *recv_buf) {
    switch (recv_buf[1]) { // 定位模块
        case LR_FRAME_TEST_LED: 
            parse_test_led_query(&recv_buf);		// 板载测试led灯 C13
            break;
		
		
		
		
        default:
            rt_kprintf("Invalid module for query command!\n");
            break;
    }
}
// 主机设置命令解析
void lora_cmd_set_parse(uint8_t *recv_buf) {
    switch (recv_buf[1]) { // 定位模块
        case LR_FRAME_TEST_LED:
            parse_test_led_set(recv_buf);		// 板载测试led灯 C13
            break;
		
		
		
        default:
            rt_kprintf("Invalid module for set command!\n");
            break;
    }
}

//处理Lora接收到的有效信息
void app_lora_data_parse(uint8_t * recv_buf)
{
#ifdef DeBug
	// 输出接收到的 除去帧头帧尾的值
	rt_kprintf("Received data: ");
	for (int i = 0; i < MAX_FRAME_LEN; i++) {
		if (recv_buf[i] == '\0') {
			break;
		}
		rt_kprintf("%02X ", recv_buf[i]);
	}
	rt_kprintf("\n");
#endif
	
	//计算此次接收的长度
    uint16_t recv_length = strlen((const char *)recv_buf);
	// 接收到的数据至少大于2
    if (recv_length < 2) {	
        rt_kprintf("Received data is too short for CRC16 check!\n");
        return;
    }
    // 找到除去crc外的有效数据长度
    uint16_t data_length = recv_length - 2;	
	// 提取接收数据中的 CRC
    uint16_t recv_crc = (recv_buf[data_length] << 8) | recv_buf[data_length + 1];

    // 计算 CRC16
    uint16_t calculated_crc = CRC16(recv_buf, data_length);

    // 校验 CRC16
    if (calculated_crc == recv_crc) {
        // CRC16 校验通过，处理有效数据
		switch(recv_buf[0])	// -------定位操作码
		{
			case LR_FRAME_QUERY	:	lora_cmd_query_parse(recv_buf); break;	//查询命令
			case LR_FRAME_SET  	:	lora_cmd_set_parse(recv_buf);	break;	//设置命令
			default: rt_kprintf("Invalid operation code!\n");		break;	//无效的操作码
		}
		
#ifdef DeBug
        rt_kprintf("CRC16 check passed! parseing data...\n");
		// 输出有效数据
        for (int i = 0; i < data_length; i++) {
            rt_kprintf("data %d:%02X \n", i+1,recv_buf[i]);
        }
        rt_kprintf("\n");
#endif
		
    } else {
        // CRC16 校验失败
        rt_kprintf("CRC16 check failed! Received CRC: %04X, Calculated CRC: %04X\n", recv_crc, calculated_crc);
    }
	
	
	
}
//Lora接收的有效信息的处理  线程
void app_lora_data_parse_thread(void* parameter)
{
	uint8_t* recv_buf = RT_NULL;
	while(1)
	{
		// 为 recv_buf 分配内存
        recv_buf = rt_malloc(MAX_FRAME_LEN);
        if (recv_buf == RT_NULL) {
            // 内存分配失败，处理错误
            rt_kprintf("app_lora_data_parse_thread: Failed to allocate memory for recv_buf!\n");
            continue;
        }
		
		// 等待接收到数据
		rt_err_t result = rt_mq_recv(mq_Lora_rx, recv_buf, MAX_FRAME_LEN, RT_WAITING_FOREVER);
		
		if(result == RT_EOK)
		{
			app_lora_data_parse(recv_buf);	//判断命令
			
			rt_free(recv_buf);	//释放空间
		}
		
	}
}

void app_lora_tx_thread(void* parameter)
{
	uint8_t tx_buff[32];	//发送数组
	
	while(1)
	{
		
	
	
	}
}

//Lora模块 模式配置函数
void lora_mode_config(enum lora_mode mode)
{
	rt_thread_delay(100);
    switch(mode)
    {
        case lora_mode_transfer : LORA_M0(0); LORA_M1(0); break;
        case lora_mode_wor      : LORA_M0(1); LORA_M1(0); break;
        case lora_mode_conf     : LORA_M0(0); LORA_M1(1); break;
        case lora_mode_sleep    : LORA_M0(1); LORA_M1(1); break;
        default                 : break;
    }
    rt_thread_delay(100);
}


//初始化Lora
void app_lora_init(void)
{
    /* 初始化缓冲区读写位置 */
    lora_rx_buff.rd = 0;
    lora_rx_buff.wr = 0;

	
	rt_thread_t thread_Lora_RxData;  		//读环形缓冲区任务句柄
	rt_thread_t thread_Lora_data_parse;	//Lora接收数据处理任务句柄
	
    /* 创建信号量 */
    sem_LoraRx = rt_sem_create("sem_LoraRx",                 // 信号量名称
                                  0,                            // 初始值
                                  RT_IPC_FLAG_FIFO);            // 先进先出
	//判断信号量是否创建成功
	if(sem_LoraRx == RT_NULL) {
		rt_kprintf("Failed to create sem_LoraRx!\n");
	}
	
	// 创建消息接收队列
    mq_Lora_rx = rt_mq_create("mq_Lora_rx",
                              MAX_FRAME_LEN,  // 一个消息队列的长度单位为 byte
                              32,             // 消息队列的最大数量
                              RT_IPC_FLAG_FIFO);
    if (mq_Lora_rx == RT_NULL) {
        rt_kprintf("Failed to create mq_Lora_rx!\n");
    }
	
	// 创建消息发送队列
    mq_Lora_tx = rt_mq_create("mq_Lora_tx",
                              MAX_FRAME_LEN,  // 一个消息队列的长度单位为 byte
                              32,             // 消息队列的最大数量
                              RT_IPC_FLAG_FIFO);
    if (mq_Lora_tx == RT_NULL) {
        rt_kprintf("Failed to create mq_Lora_tx!\n");
    }
	
    /* 创建读环形缓冲区任务 */;
    thread_Lora_RxData = rt_thread_create("app_lora_rx_thread",      // 任务名称
                                       app_lora_rx_thread,      // 任务函数入口
                                       RT_NULL,                 // 参数
                                       512,                     // 栈大小
                                       5,                       // 优先级
                                       10);                     // 运行时间片
    if(thread_Lora_RxData != NULL)
        rt_thread_startup(thread_Lora_RxData);
	else
		rt_kprintf("Failed to create thread_Lora_RxData!\n");
	
	// 创建Lora接收数据处理任务
	thread_Lora_data_parse = rt_thread_create("app_lora_data_parse_thread",
										app_lora_data_parse_thread,
										RT_NULL,
										512,
										6,
										10); //lora数据处理线程	
    if(thread_Lora_data_parse != NULL)
        rt_thread_startup(thread_Lora_data_parse);
	else
		rt_kprintf("Failed to create thread_Lora_data_parse!\n");
	
	// 创建Lora发送数据处理任务
	thread_Lora_data_parse = rt_thread_create("app_lora_tx_thread",
										app_lora_tx_thread,
										RT_NULL,
										512,
										6,
										10); //lora数据处理线程	
    if(thread_Lora_data_parse != NULL)
        rt_thread_startup(thread_Lora_data_parse);
	else
		rt_kprintf("Failed to create app_lora_tx_thread!\n");
	
    /* 开启配置模式 */
    lora_mode_config(lora_mode_conf);
    
    /* 初始化Lora模块 */
    if(0)//初始化发送端(地址00 01)
    {
        uint8_t con[10] = {0xC0, 0x00, 0x07, 0x00, 0x01, 0x04, 0x62, 0x00, 0x17, 0x40};
        HAL_UART_Transmit(&huart1, con, 10, 200);
        
        /* 开启发送模式 */
        lora_mode_config(lora_mode_transfer);
        
        /* 向另一个Lora模块发送数据 */  //点对点：地址，信道，数据
        uint8_t msgs[10] = {0x00, 0x02, 0x17, 0x01, 0x02, 0x03, 0x04};
        HAL_UART_Transmit(&huart1, msgs, 7, 200); 
    }
    else
    {
		//初始化接收端Lora(地址00 02) (网络地址04)(串口9600,8N1)(信道17)(.....)
        uint8_t con[10] = {0xC0, 0x00, 0x07, 0x00, 0x02, 0x04, 0x62, 0x00, 0x17, 0x40};
        HAL_UART_Transmit(&huart1, con, 10, 200);
        /* 开启发送模式 */
        lora_mode_config(lora_mode_transfer);
    }

}
